/*************************************************************************
 *                                                                       *
 * This file is part of the FreeMAPs distribution.  For full copyright   *
 * information, see COPYRIGHT and COPYING.LESSER.                        *
 *                                                                       *
 * Author:           sqbang                                              *
 * Email:            sqbang@ustc.edu                                     *
 * Date:             2011.09.08                                          *
 *                                                                       *
 *************************************************************************/

#ifndef FreeMAPs_include_COMMON_info_TimePatch_h
#define FreeMAPs_include_COMMON_info_TimePatch_h

#include "FreeMAPsConfig.h"

//C++ headers
#include <map>
#include <vector>

//COMMON headers
#include "COMMON/base/StateIndicator.h"
//#include "COMMON/enum/TimeIncrementController.h"
//#include "COMMON/enum/Triple.h"

namespace FreeMAPs
{

/**
 * TimePatch is used for each ensemble.
 * each ensemble has it's own time information such as start time and end time.
 * it can be accessed from InfoManager->get_time_info()->get_time_patch (patch_name)
 *
 * @see TimeInfo.h
 */
class TimePatch : public StateIndicator
{
public:

    class AutoControllerParameters
    {
    public:

        inline AutoControllerParameters();

        double absolute_error;
        double relative_error;
        double ratio_of_local_error;
    };

public:

    /**
     * make sure the patch name is the object's full name
     * that contains this patch.
     * it will be referenced by it's name,
     * so when an object want to use it's time_patch,
     * it search it in TimeInfo by it's full name.
     */
    TimePatch(
        const std::string& parent_name,
        const std::string& patch_name,
        const bool is_global);

public:

    inline bool
    is_global() const;

    /**
     * @return true if current time in the time info's range
     */
//    inline bool
//    is_current_time_in_range() const;

//    inline void
//    set_time_increment_controller(
//        const TimeIncrementController controller);

    inline double
    get_start_time() const;

    inline void
    set_start_time (
        const double start_time);

    inline double
    get_end_time() const;

    inline void
    set_end_time(
        const double end_time);

    inline double
    get_fixed_dt() const;

    inline void
    set_fixed_dt (
        const double fixed_dt);//dt

//    inline double
//    get_max_dt() const;

//    inline void
//    set_max_dt (
//        const double max_dt);

//    inline double
//    get_CFL_number() const;

//    inline TimeIncrementController
//    get_time_increment_controller() const;

//    inline Triple
//    is_dimensional() const;

//    inline const AutoControllerParameters&
//    get_auto_controller_parameters()const;

//    inline void
//    set_dimensional_flag(
//        const Triple dimensional_flag);

public:

    void
    clear();

//    void
//    tag_in_range (
//        const double current_time) const;
//Backward differentiation formula coef, index=0 ~ d_time_accuracy_order
//    double get_BDF_coef(int index)const;
    /**
     * dimentionalize the time information, that means all data*characteristic_scale.
     */
//    void
//    dimentionalize();

    /**
     * nondimentionalize the time information, that means all data/characteristic_scale.
     */
//    void
//    nondimentionalize();

    void
    get_from_input (
        const InputDatabase* db);

    friend std::ostream&
    operator << (
        std::ostream& os,
        const TimePatch& rhs);


    bool
    check_all_info_db(const InputDatabase* db);


private:

    typedef StateIndicator Parent;

    /*
     * the global time info will be used as default if local time info has not been set.
     */
    bool d_is_global;

    double d_start_time;
    double d_end_time;

    /*
     * fixed dt is used when time increment controller =FIXED
     */
    double d_fixed_dt;

    /*
     * the dt must NOT greater than d_max_dt at any case.
     */
    double d_max_dt;
    double d_cfl_number;
//    TimeIncrementController d_time_increment_controller;
//    AutoControllerParameters d_auto_controller_paras;

    /*
     * indicate whether the data is dimensional
     * or nondimensional by divided a characteristic_scale.
     */
//    Triple d_is_dimensional;

    /*
     * indicate whether the current time patch contains the current time.
     * it will decided whether the object that use this time patch will be solved or not.
     */
    mutable bool d_is_current_time_in_range;
    // time accuracy order, 1 is one order BDF, now only smaller than 7 is support;
    int d_time_accuracy_order;
};

}

#include "COMMON/info/TimePatch.inl"

#endif
